"""
获取网络资源组件
"""
import gzip
import json
import typing
from .framework import session_received, dispatch
from .base import BaseSession, BaseSessionParentType, BaseSessionType
from .utils import to_any, callback


@session_received
class Requests(BaseSession):
    """
    根据指定的网址和附加信息获取特定网页内容
    使用此组件的get, post调用客户端的网络功能获取网页
    """

    name: typing.ClassVar[str] = "Requests"

    @classmethod
    async def create(cls: typing.Type[BaseSessionType], parent: BaseSessionParentType, *args: typing.Any,
                     **kwargs: typing.Dict) -> BaseSessionType:
        return await super().create(parent, *args, **kwargs)

    async def on_receive(self, msg):
        match msg.name:
            case 'onResult':
                dispatch(self.on_result(*msg.argv, session_id=msg.session, future_id=msg.future))
                return
            case _:
                await super().on_receive(msg)

    async def get(self, url: str, headers: dict = {}):
        """
        客户端使用 GET 方式获取 url 的内容
        返回一个状态码，响应头，响应体的元组
        返回值： 元组类型
            元素1：state_code(数值类型，一般获取成功等于200）
            元素2: headers(字典类型， 响应头的键值对)
            元素3: body(字节类型， 转换成文本需要解码)
        示例：
            state_code, responce_headeers, body = await requests.get(url, request_headers)
        """
        _headers = json.dumps(headers)
        return await self.send_action_until_return('get', to_any(url), to_any(_headers))

    async def post(self, url: str, headers: dict = {}, data: dict = {}):
        """
        客户端使用 POST 方式获取 url 的内容
        返回一个状态码，响应头，响应体的元组
        示例：
            state_code, responce_headeers, body = await requests.post(url, request_headers, data)
        """
        _headers, _data = json.dumps(headers), json.dumps(data)
        return await self.send_action_until_return('post', to_any(url), to_any(_headers), to_any(_data))

    @callback(int, str, bytes)
    async def on_result(self, *result, session_id, future_id):
        """
        当获取网页成功后，此方法被自动调用。
        通常不需要关注此方法的实现。
        """
        _headers = json.loads(result[1])
        body = gzip.decompress(result[2])
        self.set_action_result(session_id, future_id, (result[0], _headers, body))
